package main

import (
	"encoding/json"
	"fmt"
)

/*
JSON解析介绍
JSON解析就是将JSON转换为Go数据类型。
*/
func main() {

	/*
		一. JSON转切片
	*/
	s := `{"code":"000000","data":"1233","message":"success"}`
	s2 := `{
	   "Code": "000000",
	   "DAta": "ResponseInfo",
	   "Message": "responseInfoSuccess",
       "tags": [
			"Apple", 
			"Banana", 
			"Orange"
		],
		"id": 123456678
 	}`
	s3 := `[
	   {
		 "Code": "111111",
		 "DAta": "",
		 "Message": "fail"
	   },
	   {
		 "Code": "000000",
		 "DAta": "434",
		 "Message": "success"
	   }
	 ]`
	// s1
	var info map[string]interface{}
	if err := json.Unmarshal([]byte(s), &info); err == nil {
		fmt.Println(info)
		for s2, i := range info {
			fmt.Print("s1 key: ", s2)
			fmt.Println(", s1 value: ", i)
		}
	} else {
		fmt.Println(err.Error())
	}
	// 清空map
	info = make(map[string]interface{})
	// s2
	if err := json.Unmarshal([]byte(s2), &info); err == nil {
		fmt.Println(info)
		for s2, i := range info {
			fmt.Print("s2 key: ", s2)
			fmt.Println(",s2 value: ", i)
		}
	} else {
		fmt.Println(err.Error())
	}
	// s3
	var arrInfo []map[string]interface{}
	if err := json.Unmarshal([]byte(s3), &arrInfo); err == nil {
		fmt.Println(info)
		for s2, i := range arrInfo {
			fmt.Print("s3 key: ", s2)
			fmt.Println(",s3 value: ", i)
			for s4, i2 := range i {
				fmt.Print("s4 key: ", s4)
				fmt.Println(",s4 value: ", i2)
			}
		}
	} else {
		fmt.Println(err.Error())
	}

	/*
		二. JSON转结构体
			同编码一样，json包是通过反射机制来实现解码的，因此结构体必须导出所转换的字段，不导出的字段不会被json包解析。
			另外解析时不区分【JSON中key】的大小写
	*/
	// 单个
	var responseInfo Response
	if err := json.Unmarshal([]byte(s), &responseInfo); err == nil {
		fmt.Println(responseInfo)
	} else {
		fmt.Println(err.Error())
	}
	if err := json.Unmarshal([]byte(s2), &responseInfo); err == nil {
		fmt.Println(responseInfo)
	} else {
		fmt.Println(err.Error())
	}
	// 数组
	var responseInfoArr []Response
	if err := json.Unmarshal([]byte(s3), &responseInfoArr); err == nil {
		fmt.Println(responseInfoArr)
		for i, i2 := range responseInfoArr {
			fmt.Println(i, ": ", i2)
		}
	} else {
		fmt.Println(err.Error())
	}
	// 结构体字段标签接受JSON解析，如果标签标记为"-"，将被忽略
	var responseTar ResponseTar
	s4 := `{"_code":"000000","d_ata":"1233","_message":"success",
			"Place": "上海嘉定","number": "1234321122323","id": 3323232}`
	if err := json.Unmarshal([]byte(s4), &responseTar); err == nil {
		fmt.Println(responseTar)
	} else {
		fmt.Println(err.Error())
	}
	// s5
	s5 := `{
		"_code":"000000",
		"d_ata":"1233",
		"_message":"success",
		"Card2Tar":{
			"Place": "通过对象形式",
			"Number": "1234321122323"
		},
		"Place": "结构体不存在此字段会在匿名字段中寻找",
		"number": "1234321122323",
		"id": 3323232
	}`
	var responseTar1 ResponseTar
	if err := json.Unmarshal([]byte(s5), &responseTar1); err == nil {
		fmt.Println("s5:", responseTar1)
	} else {
		fmt.Println(err.Error())
	}
	// s6
	s6 := `{
		"_code":"000000",
		"d_ata":"1233",
		"_message":"success",
		"Card2Tars":[{
			"Place": "通过对象形式11",
			"Number": "1234321122323"
		},
		{
			"Place": "通过对象形式22",
			"Number": "1234321122323"
		}
		],
		"Place": "结构体不存在此字段会在匿名字段中寻找",
		"number": "1234321122323",
		"id": 3323232
	}`
	var responseTar2 ResponseTar
	if err := json.Unmarshal([]byte(s6), &responseTar2); err == nil {
		fmt.Println("s6:", responseTar2)
	} else {
		fmt.Println(err.Error())
	}
	// s7
	s7 := `[{
		"_code":"000000",
		"d_ata":"1233",
		"_message":"success",
		"Card2Tars":[{
			"Place": "通过对象形式11",
			"Number": "1234321122323"
		},
		{
			"Place": "通过对象形式22",
			"Number": "1234321122323"
		}
		],
		"Place": "结构体不存在此字段会在匿名字段中寻找",
		"number": "1234321122323",
		"id": 3323232
	},
	{
		"_code":"000002",
		"d_ata":"1232",
		"_message":"success2",
		"Card2Tars":[{
			"Place": "通过对象形式112",
			"Number": "1234321122323"
		},
		{
			"Place": "通过对象形式222",
			"Number": "1234321122323"
		}
		],
		"Place": "结构体不存在此字段会在匿名字段中寻找",
		"number": "1234321122323",
		"id": 3323232
	}]`
	var responseTar3 []ResponseTar
	if err := json.Unmarshal([]byte(s7), &responseTar3); err == nil {
		fmt.Println("s7:", responseTar3)
	} else {
		fmt.Println(err.Error())
	}
}

type Response struct {
	Code    string
	DAta    string
	Message string
	id      int // 未导出字段(首字母小写)JSON解析时受影响
}

/*
结构体字段标签Json解析
*/
type ResponseTar struct {
	CardTar // 匿名字段

	Card2Tar Card2Tar

	Card2Tars []Card2Tar

	Number  string // 在解码JSON时，如果找不到字段，则再查找匿名字段中的字段
	Code    string `json:"_code"`
	DAta    string `json:"d_ata"`
	Message string `json:"-"`  // "-" 忽略解析Message字段
	Id      int    `json:"id"` // 未导出字段(首字母小写)JSON解析时受影响
	Tags    []string
}

type CardTar struct {
	Number string
	Place  string
}

type Card2Tar struct {
	Number string
	Place  string
}
